Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 25 Entwickeln von Steuerelementen
  gp 25.1 Einführung
    gp 25.1.1 Entwicklungsszenarien
    gp 25.1.2 Testen eines Steuerelements
  gp 25.2 Steuerelemente mit »UserControl«
    gp 25.2.1 Beispielprogramm eines Benutzersteuerelements
    gp 25.2.2 Die Eigenschaften des Benutzersteuerelements
    gp 25.2.3 Attribute zur Beeinflussung eines Benutzersteuerelements
    gp 25.2.4 Ereignisse des Benutzersteuerelements
    gp 25.2.5 Bereitstellen einer Toolbox-Bitmap
    gp 25.2.6 Zusammenfassung des Codes für »EllipseLabel«
  gp 25.3 Ableiten eines vorhandenen Steuerelements
  gp 25.4 Ein eigenes Steuerelement entwerfen


Galileo Computing

25.2 Steuerelemente mit »UserControl«  downtop

Um aus einem oder mehreren vorhandenen Steuerelementen ein neues Steuerelement zu erzeugen, müssen Sie ein Projekt vom Typ Windows-Steuerelementbibliothek anlegen (siehe Abbildung 25.2). Dazu sollten Sie der Projektmappe einen anderen Namen geben als dem Projekt des Steuerelements. Wenn Sie später zu Testzwecken der Projektmappe eine Windows-Anwendung hinzufügen, erleichtern Sie sich die Entwicklungsarbeit durch eine klare Trennung der jeweiligen Projektdateien.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 25.2     Anlegen eines Projekts vom Typ »Windows-Steuerelementbibliothek«


Hinweis

Sie können auch über das Menü Projekt der Entwicklungsumgebung dem aktuellen Projekt ein eigenes Steuerelement bereitstellen. Wenn das aktuelle Projekt aber zu einer EXE-Datei kompiliert wird, haben Sie keine Möglichkeit, das Benutzersteuerelement auch in anderen Anwendungen einzusetzen. Daher halte ich diese Vorgehensweise für weniger empfehlenswert.


Haben Sie die Angaben bestätigt, öffnet sich die Entwicklungsumgebung und zeigt im Designer eine Ansicht, die an eine Form ohne Rahmen und Titelleiste erinnert. Tatsächlich handelt es sich dabei bereits um das neue Steuerelement, obwohl es noch keinerlei Fähigkeiten hat und auch keine optisch erkennbare Oberfläche aufweist. Die angezeigte Fläche dient dazu, die Steuerelemente aufzunehmen, aus denen sich das neue Steuerelement zusammensetzt.

Der Klassenname und damit auch der Typ des Steuerelements lautet zunächst UserControl1 und sollte durch einen passenderen ersetzt werden. Die Implementierung des Benutzersteuer-elements muss während der Entwicklungsphase natürlich dauernd getestet werden. Dazu sollte die Projektmappe von Anfang an durch ein Projekt des Typs Windows-Anwendung ergänzt werden. Vergessen Sie nicht, dass beim Start der Laufzeit aus der Entwicklungsumgebung heraus die Hostanwendung gestartet werden muss. Da immer das Projekt, das zuerst zu der Projektmappe gehört, das Startprojekt ist, müssen Sie noch im Kontextmenü der Windows-Anwendung Als Startprojekt festlegen auswählen.


Galileo Computing

25.2.1 Beispielprogramm eines Benutzersteuerelements  downtop

Wir wollen uns im Folgenden die Entwicklung eines Benutzersteuerelements an einem konkreten Beispiel ansehen. Das neue Steuerelement soll relativ einfach sein und als eine Erweiterung des herkömmlichen Labels dienen. Die Erweiterung wird aber nicht durch zusätzliche Verhaltensweisen beschrieben, vielmehr soll um den angezeigten Text eine Ellipse in einem beliebigen Farbton gezeichnet werden. Das neue Steuerelement, dessen Typbezeichner EllipseLabel lauten soll, löst unter anderem das Click-Ereignis aus, wenn sich der Mauszeiger in der Ellipse befindet.

Die grafische Oberfläche des Benutzersteuerelements

Die Steuerelemente, aus denen sich ein Benutzersteuerelement zusammensetzt, werden als konstituierende Steuerelemente bezeichnet. Unser neues Control enthält nur ein konstituierendes Steuerelement, nämlich ein Label, das beliebig auf der Oberfläche positioniert werden darf. Zur Laufzeit soll dessen Beschriftung zentral im Control angezeigt werden. Das können wir aber nur mittels Programmcode erreichen, weil zur Entwurfszeit weder die Abmessungen des EllipseLabel-Objekts noch die Textlänge bekannt sind. Allerdings muss die Eigenschaft AutoSize=True gesetzt werden, um sicherzustellen, dass sich die Abmessung des Labels automatisch der Beschriftung anpasst.

Konstituierende Steuerelemente sind Komponenten des Benutzersteuerelements, auf die ein Entwickler (also derjenige, der das fertige Steuerelement einsetzt) keinen Zugriff haben sollte. Die Sichtbarkeit ist daher meistens Private. Allerdings sollten Sie berücksichtigen, dass das Benutzersteuerelement später möglicherweise abgeleitet werden soll. Dann muss das Label auch in der abgeleiteten Klasse sichtbar sein, was den Modifizierer Protected erforderlich macht. Die Vorgabe bei konstituierenden Steuerelementen ist Friend.


Public Class EllipseLabel
Inherits UserControl
Protected label1 As Label
...
End Class

Die Ellipse soll an den vier Rändern des Steuerelements anstoßen und mit einer Farbfüllung gezeichnet werden. Grundsätzlich eignet sich, wie bei anderen Komponenten auch, das Ereignis Paint des Benutzersteuerelements für alle Zeichenoperationen. Mit der Methode FillEllipse, die im ersten Parameter ein farbbeschreibendes Brush-Objekt erwartet, zeichnen wir die Ellipse. Die Farbfüllung wird durch die Referenz fillColor vom Typ SolidBrush beschrieben und auf Klassenebene festgelegt. Die Standardfarbe sei Blau.


Protected cfillColor As SolidBrush = New SolidBrush(Color.Blue)

Im Paint-Ereignis des Benutzersteuerelements wird auch die Zeichenfolge des Labels ausgerichtet. Dazu werden zuerst die Koordinaten des Ursprungspunktes ermittelt, die anschließend der Eigenschaft Location als Point-Referenz übergeben werden.


Private Sub EllipseLabel_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim graph As Graphics = e.Graphics
graph.FillEllipse(cfillColor, 0, 0, Me.ClientSize.Width, _
Me.ClientSize.Height)
Dim x As Integer = (Me.ClientSize.Width – _
Label1.ClientSize.Width) / 2
Dim y As Integer = (Me.ClientSize.Height – _
Label1.ClientSize.Height) / 2
Label1.Location = New Point(x, y)
End Sub

Nun soll das Benutzersteuerelement zum ersten Mal in der Windows-Testanwendung ausprobiert werden. Voraussetzung dazu ist ein Kompilat, deshalb ist zuerst eine Kompilierung notwendig. Anschließend ergänzen Sie die Projektmappe um ein Windows-Projekt und ziehen eine Instanz des Benutzersteuerelements aus der Toolbox in die Form.

Der Feinschliff der grafischen Anzeige

Sehen wir uns die Instanz des Benutzersteuerelements in der Form kritisch an. Was sofort auffällt, ist, dass die Hintergrundfarbe des Labels der Hintergrundfarbe der Form entspricht. Das sollte natürlich nicht der Fall sein, denn die Farbe sollte sich der Farbe der umgebenden Ellipse anpassen. Außerdem tritt beim schnellen Verändern der Größe des EllipseLabel-Objekts ein unangenehmes Flimmern auf. Beide Effekte sollen nun beseitigt werden. In diesem Zusammenhang lernen wir eine neue Methode der Control-Klasse kennen, die uns bisher noch nicht begegnet ist: Es ist die geschützt definierte Methode SetStyle.


Protected Sub SetStyle(ControlStyles, Boolean)

Mit der Übergabe von ControlStyles wird auf das Verhalten und die Darstellung eines Steuerelements Einfluss geübt. ControlStyles ist eine Enumeration, die über das Flags-Attribut verfügt, d. h., die einzelnen Konstanten werden bitweise miteinander kombiniert. Der zweite Parameter gibt an, ob die angeführten Formatbits gesetzt werden sollen (True) oder nicht (False).

Tabelle 25.1 enthält einen Auszug der möglichen Formatbits. Die Beschreibung bezieht sich dabei auf gesetzte Formatbits (True).


Tabelle 25.1     Mitglieder der Enumeration »ControlStyles« (Auszug)

Member Beschreibung
ContainerControl Das Steuerelement ist gleichzeitig ein Steuerelementcontainer.
DoubleBuffer Die Zeichenoperation wird so lange gepuffert, bis sie vollständig ausgeführt ist. Gleichzeitig müssen auch die Formatbits UserPaint und AllPaintingInWmPaint auf True gesetzt werden.
FixedHeight Das Steuerelement behält auch bei einer Skalierung seine Höhe bei.
FixedWidth Das Steuerelement behält auch bei einer Skalierung seine Breite bei.
Opaque Mit der Einstellung True wird das Steuerelement nicht transparent gezeichnet.
ResizeRedraw Das Steuerelement wird bei einer Änderung der Größe neu gezeichnet.
Selectable Das Steuerelement kann den Fokus erhalten.
StandardClick Das Steuerelement implementiert das Standard-Click-Verhalten.
StandardDoubleClick Das Steuerelement implementiert das Standard-DoubleClick-Verhalten, falls StandardClick nicht True ist.
SupportsTransparentBackColor Das Steuerelement simuliert Transparenz.
UserMouse Das Steuerelement führt eine eigene Verarbeitung von Mauseingaben durch. Die Mausereignisse werden nicht vom Betriebssystem behandelt.
UserPaint Das Steuerelement zeichnet sich selbst, so dass es nicht vom Betriebssystem gezeichnet werden muss.

Mit SetStyle werden die Formatbits festgelegt, mit GetStyle kann bei Bedarf der Zustand eines bestimmten Bits abgerufen werden:


Protected Function GetStyle(ControlStyles) As Boolean

Mit den neuen Kenntnissen können wir jetzt zur Tat schreiten und zur Vermeidung des Flimmerns die Doppelpufferung im Load-Ereignishandler aktivieren. Zum Schluss wird noch die Hintergrundfarbe auf Color.Transparent festgelegt, die zusammenfassend wie folgt codiert ist:


Private Sub EllipseLabel_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
Me.SetStyle(ControlStyles.DoubleBuffer Or _
ControlStyles.UserPaint Or _
ControlStyles.AllPaintingInWmPaint Or _
ControlStyles.SupportsTransparentBackColor Or _
ControlStyles.ResizeRedraw, True)
Me.BackColor = Color.Transparent
End Sub


Galileo Computing

25.2.2 Die Eigenschaften des Benutzersteuerelements  downtop

Das Benutzersteuerelement erbt von Control bereits eine stattliche Anzahl von Eigenschaften, wie im Eigenschaftsfenster der Hostanwendung zu sehen ist. Beispielsweise können wir das Steuerelement andocken und sogar die Schriftfarbe mit der Eigenschaft ForeColor ändern, ohne eine Zeile Programmcode schreiben zu müssen. Natürlich soll unser Steuerelement auch eigene, spezifische Eigenschaften aufweisen. Um zwei Eigenschaften werden wir daher unser Steuerelement erweitern. Die erste Eigenschaft ist Text und dient dazu, die Beschriftung zu ändern. Mit der zweiten, FillColor, ermöglichen wir dem Anwender, eine andere Füllfarbe der Ellipse einzustellen.

Die Eigenschaft Text wird durch die Klasse Control der Klasse UserControl vererbt. Wir müssen sie daher nur passend überschreiben. Was die Eigenschaft Text anzeigen soll, ist der Inhalt der Text-Eigenschaft des Label-Steuerelements, die jedoch nicht direkt von außen manipuliert werden kann, weil das konstituierende Steuerelement privat deklariert ist. Daher leiten wir die Aufrufe an die Eigenschaft Text des Benutzersteuerelements nur an den entsprechenden Accessor weiter.


Public Overrides Property Text() As String
Get
Return Me.Label1.Text
End Get
Set(ByVal value As String)
Me.Label1.Text = value
End Set
End Property

Es erweist sich hier als vorteilhaft, die Eigenschaft AutoSize des Labels auf True gesetzt zu haben, denn bei einer Änderung der Zeichenfolge passt sich die Größe des Labels automatisch an. Das hat aber auch zur Folge, dass das Paint-Ereignis des Benutzersteuerelements aufgerufen und das Label neu zentriert wird.

Die Eigenschaft FillColor zum Ändern der Füllfarbe kann nicht von einer Eigenschaft des Labels profitieren. Weiter oben hatten wir deshalb die Variable fillColor vom Typ SolidBrush deklariert und eine blaue Füllfarbe zum Standard erklärt. Mit FillColor ermöglichen wir nun dem Anwender, die Farbe nach eigenen Vorstellungen festzulegen. Damit sich die Änderungen sofort in der Hostanwendung auswirken, müssen wir hier das Paint-Ereignis manuell auslösen.


Public Property FillColor() As Color
Get
Return cfillColor.Color
End Get
Set(ByVal value As Color)
Me.cfillColor.Color = value
Me.Invalidate()
End Set
End Property

Nach diesen beiden Ergänzungen sollten wir das Steuerelement kompilieren und in der Hostanwendung testen. Dabei interessiert insbesondere das Eigenschaftsfenster der Steuerelementinstanz.

Die Eigenschaft FillColor bietet bei einer beabsichtigten Änderung sofort den bekannten Auswahldialog für Farben an. Das ist vielleicht schon mehr, als zu vermuten war. Die Wahl einer Farbe wird im Designer auch mit dem sofortigen Farbwechsel beantwortet. Es fallen aber auch noch zwei andere Dinge auf. Am Fußende des Eigenschaftsfensters wird optional eine Kurzbeschreibung der markierten Eigenschaft angezeigt. Die Beschreibung von FillColor ist allerdings leer. Außerdem wird FillColor bei einer kategorisierten Eigenschaftsanzeige unter der Kategorie Sonstiges aufgeführt, obwohl die Kategorie Darstellung dazu besser geeignet wäre.

Die Eigenschaft Text werden Sie im Eigenschaftsfenster vergeblich suchen. Sie wird nicht angezeigt. Somit besteht bei dem augenblicklichen Entwicklungsstand auch keine Möglichkeit, die Beschriftung des Steuerelements im Eigenschaftsfenster zu ändern. Lassen Sie sich andererseits im Codeeditor die IntelliSense-Liste der EllipseLabel-Instanz anzeigen, können Sie der Eigenschaft einen anderen Wert zuweisen.

Einer dritten Eigenschaft sollten wir auch noch Beachtung schenken. Es ist BackColor. Voreingestellt ist Transparent, aber die Wahl einer anderen Hintergrundfarbe, die von der Hintergrundfarbe der Form abweicht, ist durchaus möglich. Man kann natürlich darüber streiten, ob man das als Autor eines Benutzersteuerelements zulassen möchte, aber wir legen an dieser Stelle einfach fest, dass eine Änderung nicht erlaubt sein soll.


Galileo Computing

25.2.3 Attribute zur Beeinflussung eines Benutzersteuerelements  downtop

Damit stehen wir vor einigen Problemen, die gelöst werden müssen. Das .NET Framework bietet dazu zahlreiche Attribute an, mit denen das Verhalten eines Benutzersteuerelements in der Hostanwendung beeinflusst werden kann. Sehen wir uns zunächst einige Attribute an, die im Zusammenhang mit der Entwicklung eines Benutzersteuerelements eine wichtige Rolle einnehmen.


Tabelle 25.2     Attribute eines Benutzersteuerelements (Auszug)

Attribut Beschreibung
Browsable Dieses Attribut gibt an, ob eine Eigenschaft im Eigenschaftsfenster angezeigt wird oder nicht.
Category Dieses Attribut gibt an, welcher Kategorie die Eigenschaft im Eigenschaftsfenster zugeordnet werden soll. Die Klasse definiert dazu Kategorien, die aber auf Wunsch auch durch eigene mit beliebiger Bezeichnung ergänzt werden dürfen.
Description Dieses Attribut definiert die Zeichenfolge, die am Fuß des Eigenschaftsfensters eingeblendet wird.
DefaultEvent Legt das Standardereignis des Steuerelements fest. Wird im Designer auf das Steuerelement doppelt geklickt, wird automatisch der Ereignishandler des Standardereignisses erzeugt.
DefaultProperty Legt die Standardeigenschaft des Steuerelements fest. Die Standardeigenschaft wird im Eigenschaftsfenster markiert, wenn der Benutzer im Designer auf das Steuerelement klickt.
DefaultValue Dieses Attribut legt den Standardwert der Eigenschaft fest.
EditorBrowsable Dieses Attribut ermöglicht, eine Eigenschaft oder Methode aus der IntelliSense-Liste ein- oder auszublenden.
RefreshProperties Mit diesem Attribut kann festgelegt werden, ob und wie bei einer Änderung der Eigenschaft der Designer aktualisiert wird.

Diese Liste dieser im Namespace System.ComponentModel enthaltenen Attribute ist nicht vollständig, aber sie vermittelt schon einen Eindruck darüber, dass viele weitergehende Manipulationen möglich sind. Wir werden im Laufe dieses Kapitels auch noch Attribute benutzen, die in dieser Tabelle nicht enthalten sind.

Anpassen der Eigenschaften des »EllipseLabel«-Steuerelements

Wir wollen nun sehen, wie wir die Attribute sinnvoll auf die drei Eigenschaften BackColor, FillColor und Text anwenden können.

Fangen wir mit BackColor an. Diese Eigenschaft wird im Eigenschaftsfenster aufgelistet und ist damit auch editierbar. Das wollten wir abschalten. Zum Ausblenden reicht das Attribut Browsable bereits aus, aber dann könnte auf die Eigenschaft immer noch über die IntelliSense-Liste des Codeeditors zugegriffen werden. Daher ist zusätzlich auch das Attribut EditorBrowsable erforderlich, dessen Konstruktor ein Argument vom Typ der Enumeration EditorBrowsableState übergeben wird, die drei Konstanten beschreibt: Advanced, Always und Never. Die letztgenannte Konstante ist die, die wir dem EditorBrowsable-Attribut übergeben müssen.

Da wir nun an der geerbten Verhaltensweise Änderungen vornehmen, muss die Eigenschaft BackColor überschrieben werden. Mit MyBase greifen wir dabei auf die ursprüngliche Funktionalität zu.


<EditorBrowsable(EditorBrowsableState.Never)> _
<Browsable(False)> _
Public Overrides Property BackColor() As Color
Get
Return MyBase.BackColor
End Get
Set(ByVal value As Color)
MyBase.BackColor = Color.Transparent
End Set
End Property

FillColor wird sowohl im Eigenschaftsfenster als auch in der IntelliSense-Liste angezeigt. Die Eigenschaft verknüpfen wir mit den beiden Attributen Category und Description und übergeben den Konstruktoren der beiden Attribute die entsprechende Zeichenfolge. Bei Category darf das auch die englische Bezeichnung der Kategorie sein, so können aber durchaus auch eine eigene Kategorie kreieren.

An der Codeimplementierung von FillColor ändert sich nichts.


<Description("Legt die Füllfarbe der Ellipse fest")> _
<Category("Appearance")> _
Public Property FillColor() As Color
...
End Property

Kommen wir nun zu der Eigenschaft: Text. Im Eigenschaftsfenster wird sie nicht angezeigt, deshalb müssen wir das Attribut Browsable setzen, dem wir in diesem Fall True übergeben.


<Browsable(True)> _
Public Overrides Property Text() As String
Get
Return Me.Label1.Text
End Get
Set(ByVal value As String)
Me.Label1.Text = value
End Set
End Property

Wird das Benutzersteuerelement jetzt kompiliert und die Hostanwendung gestartet, werden Sie mit einem neuen Problem konfrontiert: Die Einstellung der Eigenschaft Text wird nach dem Start nicht beibehalten, sondern nimmt die Einstellung der Text-Eigenschaft des Labels an. Anscheinend gewährleistet die von Control geerbte Eigenschaft Text nicht, dass die Zeichenfolge serialisiert wird. Mit einem Attribut können wir auch diese Hürde meistern: dem DesignerSerializationVisibility-Attribut.

Dem Konstruktor des Attributs muss einer von drei statischen Membern der Klasse übergeben werden: Content, Hidden oder Visible. Mit Visible wird der Wert der Eigenschaft, mit dem das Attribut verknüpft ist, serialisiert, mit Hidden wird die Serialisierung unterdrückt (das ist die Vorgabe der Eigenschaft Text in Control), und mit Content wird zwar der Wert der Eigenschaft, aber nicht die Eigenschaft selbst serialisiert.

Damit lautet die endgültige Fassung der Eigenschaft Text wie folgt:


<Browsable(True)> _
<DesignerSerializationVisibility( _
DesignerSerializationVisibility.Visible)> _
Public Overrides Property Text() As String
Get
Return Me.Label1.Text
End Get
Set(ByVal value As String)
Me.Label1.Text = value
End Set
End Property

Nachdem wir nun einige Klippen überwunden haben, um zum gewünschten Ergebnis zu kommen, müssen wir auch einige positive Feststellungen registrieren. Instanziieren wir nämlich in der Form der Hostanwendung das Benutzersteuerelement, wird automatisch ein Bezeichner vergeben, welcher der üblichen Namenskonvention entspricht: Es wird der Typ des Steuerelements benutzt, ergänzt um eine Zahl. Außerdem fängt der Bezeichner mit einem Kleinbuchstaben an.

Von der Eigenschaft Text aller üblichen Steuerelemente her sind wir es gewohnt, dass nach der Instanziierung der Bezeichner des betreffenden Steuerelements dem Inhalt der Text-Eigenschaft entspricht. Auch in dieser Hinsicht benötigen wir keinen weiteren Programmcode, das UserControl nimmt uns das automatisch ab.


Galileo Computing

25.2.4 Ereignisse des Benutzersteuerelements  downtop

Das Steuerelement soll nun auch ein Click-Ereignis bereitstellen. Standardmäßig wird das Ereignis bereits von Control geerbt und ausgelöst, wenn der Anwender auf das Steuerelement klickt. Dazu gehört natürlich auch der Bereich, der in der Hintergrundfarbe der Form angezeigt wird und streng genommen nicht dem Steuerelement zuzuordnen ist. Diesen Bereich auszusparen ist kein großes Problem. Dazu müsste man nur untersuchen, ob die Farbe des Punktes, über dem sich das Klicken abgespielt hat, der Farbe des Benutzersteuerelements entspricht.

Da Click keine Mauskoordinaten bereitstellt, könnten wir uns die Bildschirmkoordinaten des Mauszeigers mit der statischen Methode MousePosition der Klasse Control besorgen und diese der Methode PointToClient übergeben, welche die Bildschirmkoordinaten in Koordinaten der Komponente umrechnet.

Die Methode, die das Resultat als booleschen Wert liefern würde, könnte wie folgt implementiert werden:


Private Function GetColor(ByVal x As Integer, _
ByVal y As Integer) As Boolean
Dim y1, y2 As Double
Dim a As Integer = Me.Width / 2
Dim b As Integer = Me.Height / 2
Dim w As Double = Math.Sqrt((1 – (x – a) ^ 2) / a ^ 2)
y1 = b * (1 – w)
y2 = b * (1 + w)
If (y > y1 AndAlso y < y2) Then
Return True
End If
Return False
End Function

Nun könnte man mit


Protected Overrides Sub OnClick(e As EventArgs)
Dim pt As Point = Me.PointToClient(Control.MousePosition)
If GetColor(pt.X, pt.Y) Then
MyBase.OnClick(e)
End If
End Sub

die geerbte Methode OnClick überschreiben, die intern GetColor aufruft und auswertet. Ist das Ergebnis True, wird der Aufruf an die Basiskomponente weitergeleitet. Damit wäre man bereits am Ziel.

Damit hätten wir zumindest schon garantiert, dass das Click-Ereignis nicht im transparenten Bereich ausgelöst wird. Trotzdem weist dieser Ansatz noch zwei Lücken auf:

1. Trifft der Anwender beim Klicken das konstituierende Steuerelement, ist nicht das UserControl, sondern das Label Empfänger des Click-Ereignisses.
       
2. Ein Mausklick in den transparenten Bereich sollte von der Hostanwendung verarbeitet werden können.
       

Widmen wir uns zunächst dem ersten Kritikpunkt. Die Lösung ist überhaupt nicht schwierig, denn dazu müssen wir das steuerelementinterne Click-Ereignis des Labels nur an die Methode OnClick des Benutzersteuerelements weiterleiten, die sich um die Verarbeitung des Ereignisses kümmert.


Private Sub Label1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Label1.Click
MyBase.OnClick(e)
End Sub

Der zweite Punkt ist etwas kniffliger. Optimal wäre es, wenn wir das Klicken in den Bereich außerhalb der Ellipse direkt an die OnClick-Methode der Form weiterleiten könnten. Allerdings ist die Methode geschützt und entzieht sich damit dem Zugriff von außerhalb. Es gibt aber auch noch einen anderen Weg, das Ziel zu erreichen. Hier hilft uns die Eigenschaft Region des UnserControls weiter.


Public Property Region As Region

Die Eigenschaft hat die Aufgabe, dem Steuerelement einen bestimmten Fensterbereich zuzuordnen. Beschrieben wird der Fensterbereich durch ein Region-Objekt, dessen Konstruktor eine GraphicPath-Objekt erwartet. Letzteres definiert endgültig den Umriss des Fensterbereichs, der in unserem Beispiel eine Ellipse ist. Den Code dazu schreiben wird ergänzend im Paint-Ereignishandler des Benutzersteuerelements.


Private Sub EllipseLabel_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim graph As Graphics = e.Graphics
' Rechteckbeschreibung
Dim rect As Rectangle = New Rectangle(0, 0, _
Me.ClientSize.Width, Me.ClientSize.Height)
graph.FillEllipse(cfillColor, rect)
Dim x As Integer = _
(Me.ClientSize.Width – Label1.ClientSize.Width) / 2
Dim y As Integer = _
(Me.ClientSize.Height – Label1.ClientSize.Height) / 2
Label1.Location = New Point(x, y)
' Festlegen des dem Steuerelement zugeordneten Fensterbereichs
Dim graphPath As GraphicsPath = New GraphicsPath()
graphPath.AddEllipse(rect)
Me.Region = New Region(graphPath)
End Sub

Standardereignis festlegen

Ein Doppelklick auf eine Komponente im Designer führt zur automatischen Erzeugung eines Ereignishandlers. Mit welchem Ereignis dieser verknüpft ist, hängt davon ab, welches Ereignis als Standardereignis der Komponente definiert ist. Bei einer Form ist es das Ereignis Load, bei einer Schaltfläche das Ereignis Click. Nehmen wir keine Änderungen vor, ist auch bei einem Benutzersteuerelement Load das Standardereignis. Mit dem Attribut DefaultEvent können wir aber ein anderes Ereignis bestimmen. Das Attribut wird vor der Class-Deklaration angegeben.


<DefaultEvent("Click")> _
Public Class EllipseLabel
...
End Class


Galileo Computing

25.2.5 Bereitstellen einer Toolbox-Bitmap  downtop

Bisher wird für das Steuerelement in der Toolbox nur die Standardbitmap eines UserControl-Steuerelements angezeigt. Das sieht natürlich nicht sehr professionell aus und soll nun durch eine steuerelementeigene Bitmap ersetzt werden.

Liegt eine Bitmap bereits vor, können Sie diese über das Kontextmenü des Projekts (Hinzufügen N Vorhandenes Element hinzufügen...) in das Benutzersteuerelementprojekt einbinden. Falls noch keine Bitmap vorliegt, können Sie sie auch direkt im Editor der Entwicklungsumgebung zeichnen. Auch hier müssen Sie den Weg über das Kontextmenü einschlagen, wählen dann allerdings Hinzufügen • Neues Element hinzufügen... Im sich öffnenden Dialogfenster wählen Sie die Vorlage Bitmapdatei aus.

Zeichnen Sie die Bitmap im Editor, müssen Sie die Größe im Eigenschaftsfenster auf 16x16 Pixel einstellen. Das ist die vorgeschriebene Größe der Toolbox-Bitmaps und gilt natürlich auch, wenn Sie eine vorhandene Bitmap einbinden. Die Anzahl der Farben ist nicht entscheidend, aber 256 dürfte wohl immer ausreichend sein.

Ist die Bitmap fertig gestellt, müssen Sie noch zwei Dinge berücksichtigen:

1. Öffnen Sie das Eigenschaftsfenster der Bitmap, und legen Sie die Eigenschaft Buildvorgang auf Eingebettete Ressource fest. Damit wird die Bitmap-Datei im Kompilat der Anwendung aufgenommen.
       
2. Der Name der Bitmap-Datei sollte dem Klassennamen des Steuerelements entsprechen. Das können Sie gegebenenfalls auch im Eigenschaftsfenster umstellen.
       

Das .NET Framework stellt mit ToolboxBitmap ein Attribut zur Verfügung, um einem Benutzersteuerelement ein Symbol zuzuordnen. Dazu übergeben Sie dem Konstruktor des Attributs entweder die Zeichenfolge mit dem Namen der Bitmap-Datei, den Datentyp der Ressource oder den Datentyp samt Angabe des Dateinamens, wobei dieser dann sogar anders lauten darf als der Klassenname des Steuerelements, beispielsweise:


<ToolboxBitmap(C:\test.bmp")> _
Public Class EllipseLabel
...
End Class


Galileo Computing

25.2.6 Zusammenfassung des Codes für »EllipseLabel«  toptop

An dieser Stelle fassen wir den Code des Benutzersteuerelements übersichtlich zusammen. Die gesamte Lösung finden Sie unter:


... \Beispiele\Kapitel 25\EllipseLabelSolution

Wenn Sie möchten, können Sie das Benutzersteuerelement auch direkt in einer Windows-Anwendung testen. Öffnen Sie dazu ein neues Projekt, binden anschließend die Datei Tollsoft.dll unter Verweise ein und fügen im letzten Schritt das Steuerelement der Toolbox hinzu. Das EllipseLabel-Steuerelement wird auch dann weiterhin angeboten, wenn Sie die Entwicklungsumgebung erneut starten.


' ----------------------------------------------------------
' Beispiel: ...\Kapitel 25\EllipseLabel
' ----------------------------------------------------------
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
<DefaultEvent("Click")> _
Public Class EllipseLabel
Protected cfillColor As SolidBrush = New SolidBrush(Color.Blue)
Private Sub EllipseLabel_Paint(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles MyBase.Paint
Dim graph As Graphics = e.Graphics
' Rechteckbeschreibung
Dim rect As Rectangle = New Rectangle(0, 0, _
Me.ClientSize.Width, Me.ClientSize.Height)
graph.FillEllipse(cfillColor, rect)
Dim x As Integer = (Me.ClientSize.Width – _
Label1.ClientSize.Width) / 2
Dim y As Integer = (Me.ClientSize.Height – _
Label1.ClientSize.Height) / 2
Label1.Location = New Point(x, y)
' Festlegen des dem Steuerelement zugeordneten Fensterbereichs
Dim graphPath As GraphicsPath = New GraphicsPath()
graphPath.AddEllipse(rect)
Me.Region = New Region(graphPath)
End Sub
Private Sub EllipseLabel_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.SetStyle(ControlStyles.DoubleBuffer Or _
ControlStyles.UserPaint Or _
ControlStyles.AllPaintingInWmPaint Or _
ControlStyles.SupportsTransparentBackColor Or
ControlStyles.ResizeRedraw, True)
Me.BackColor = Color.Transparent
End Sub
<Browsable(True)> _
<DesignerSerializationVisibility( _
DesignerSerializationVisibility.Visible)> _
Public Overrides Property Text() As String
Get
Return Me.Label1.Text
End Get
Set(ByVal value As String)
Me.Label1.Text = value
End Set
End Property
<Description("Legt die Füllfarbe der Ellipse fest")> _
<Category("Appearance")> _
Public Property FillColor() As Color
Get
Return cfillColor.Color
End Get
Set(ByVal value As Color)
Me.cfillColor.Color = value
Me.Invalidate()
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Never)> _
<Browsable(False)> _
Public Overrides Property BackColor() As Color
Get
Return MyBase.BackColor
End Get
Set(ByVal value As Color)
MyBase.BackColor = Color.Transparent
End Set
End Property
Private Sub Label1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Label1.Click
MyBase.OnClick(e)
End Sub
End Class

 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de